-- $Id: $
-- File name:   tb_AZALIA_BLOCK.vhd
-- Created:     4/21/2011
-- Author:      Brandon Blaine Gardner
-- Lab Section: 337-06
-- Version:     1.0  Initial Test Bench

library ieee;
use ieee.std_logic_1164.all;
use IEEE.std_logic_textio.all;
use std.textio.all;
library ECE337_IP;
use ECE337_IP.all;

entity tb_AZALIA_BLOCK is
generic (Period : Time := 10.416667 ns);
end tb_AZALIA_BLOCK;

architecture TEST of tb_AZALIA_BLOCK is

  function INT_TO_STD_LOGIC( X: INTEGER; NumBits: INTEGER )
     return STD_LOGIC_VECTOR is
    variable RES : STD_LOGIC_VECTOR(NumBits-1 downto 0);
    variable tmp : INTEGER;
  begin
    tmp := X;
    for i in 0 to NumBits-1 loop
      if (tmp mod 2)=1 then
        res(i) := '1';
      else
        res(i) := '0';
      end if;
      tmp := tmp/2;
    end loop;
    return res;
  end;

  component AZALIA_BLOCK
    PORT(
         CLK : IN std_logic;
         DATA_in : IN std_logic_vector (7 DOWNTO 0);
         RST : IN std_logic;
         Rx_DATA_STB : IN std_logic;
         SDI0 : IN std_logic;
         SDI1 : IN std_logic;
         Tx_DATA_STB : IN std_logic;
         ERR         : OUT    std_logic;
         CRIT        : OUT    std_logic;
         NEW_Rx_DATA : OUT    std_logic;
         REQ_Tx_DATA : OUT    std_logic;
         ADDR : OUT std_logic_vector (11 DOWNTO 0);
         BUSY : OUT std_logic;
         DATA_out : OUT std_logic_vector (7 DOWNTO 0);
         OWN_MEM : OUT std_logic;
         RE : OUT std_logic;
         RW : OUT std_logic;
         SDO : OUT std_logic;
         WE : OUT std_logic;
         SYNC : OUT std_logic
    );
  end component;
  
-- The declaration for the on-chip scalable sram model
  component scalable_off_chip_sram is
    generic (
          -- Memory Model parameters
          ADDR_SIZE_BITS  : natural  := 12;    -- Address bus size in bits/pins with addresses corresponding to 
                                               -- the starting word of the accesss
          WORD_SIZE_BYTES  : natural  := 1;      -- Word size of the memory in bytes
          DATA_SIZE_WORDS  : natural  := 1;      -- Data bus size in "words"
          READ_DELAY      : time    := 10 ns;  -- Delay/latency per read access (total time between start of supplying address and when the data read from memory appears on the r_data port)
                                               -- Keep the 10 ns delay for on-chip SRAM
          WRITE_DELAY      : time    := 10 ns    -- Delay/latency per write access (total time between start of supplying address and when the w_data value is written into memory)
                                                 -- Keep the 10 ns delay for on-chip SRAM
          );
    port  (
          -- Test bench control signals
          mem_clr        : in  boolean;
          mem_init      : in  boolean;
          mem_dump      : in  boolean;
          verbose        : in  boolean;
          init_filename  : in   string;
          dump_filename  : in   string;
          start_address  : in  natural;
          last_address  : in  natural;
          
          -- Memory interface signals
          r_enable  : in    std_logic;
          w_enable  : in    std_logic;
          addr      : in    std_logic_vector((addr_size_bits - 1) downto 0);
          data      : inout  std_logic_vector(((data_size_words * word_size_bytes * 8) - 1) downto 0)
        );
  end component scalable_off_chip_sram;

-- Insert signals Declarations here
  signal CLK : std_logic;
  signal DATA_in : std_logic_vector (7 DOWNTO 0);
  signal RST : std_logic;
  signal Rx_DATA_STB : std_logic;
  signal SDI0 : std_logic;
  signal SDI1 : std_logic;
  signal Tx_DATA_STB : std_logic;
  signal ADDR : std_logic_vector (11 DOWNTO 0);
  signal BUSY : std_logic;
  signal DATA_out : std_logic_vector (7 DOWNTO 0);
  signal OWN_MEM : std_logic;
  signal RE : std_logic;
  signal RW : std_logic;
  signal SDO : std_logic;
  signal WE : std_logic;
  signal ERR         : std_logic;
  signal CRIT        : std_logic;
  signal NEW_Rx_DATA : std_logic;
  signal REQ_Tx_DATA : std_logic;
  signal SYNC : std_logic;

-- SRAM signals
  signal tb_data : std_logic_vector(7 downto 0);
  signal tb_mem_clr : boolean;
  signal tb_mem_init : boolean;
  signal tb_mem_dump : boolean;
  signal tb_verbose : boolean;
  signal tb_init_filename : string(23 downto 1);
  signal tb_dump_filename : string(23 downto 1);
  signal tb_start_address : natural;
  signal tb_last_address : natural;

begin

CLKGEN: process
  variable CLK_tmp: std_logic := '0';
begin
  CLK_tmp := not CLK_tmp;
  CLK <= CLK_tmp;
  wait for Period/2;
end process;

  DUT: AZALIA_BLOCK port map(
                CLK => CLK,
                DATA_in => DATA_in,
                RST => RST,
                Rx_DATA_STB => Rx_DATA_STB,
                SDI0 => SDI0,
                SDI1 => SDI1,
                Tx_DATA_STB => Tx_DATA_STB,
                ADDR => ADDR,
                BUSY => BUSY,
                DATA_out => DATA_out,
                OWN_MEM => OWN_MEM,
                RE => RE,
                RW => RW,
                SDO => SDO,
                WE => WE,
                ERR => ERR,
                CRIT => CRIT,
                NEW_Rx_DATA => NEW_Rx_DATA,
                REQ_Tx_DATA => REQ_Tx_DATA,
                SYNC => SYNC
                );
                
-- map an instance of the on-chip scalable sram model
  Memory: scalable_off_chip_sram
    port map  (
                -- Test bench control signals
                mem_clr        => tb_mem_clr,
                mem_init      => tb_mem_init,
                mem_dump      => tb_mem_dump,
                verbose        => tb_verbose,
                init_filename  => tb_init_filename,
                dump_filename  => tb_dump_filename,
                start_address  => tb_start_address,
                last_address  => tb_last_address,
                
                -- Memory interface signals
                r_enable  => RE,
                w_enable  => WE,
                addr      => ADDR,
                data      => tb_data
              );

-- connect up to the bidirectional data bus
  IO_DATA: process ( RW, tb_data, DATA_out )
  begin
    if (RW = '1') then
      -- Read mode -> the data pins should connect to the r_data bus & the other bus should float
      DATA_in  <= tb_data;
      tb_data  <= (others=>'Z');
    elsif(RW = '0') then
      -- Write mode -> the data pins should connect to the w_data bus & the other bus should float
      DATA_in  <= (others=>'Z');
      tb_data  <= DATA_out;
    else
      -- Disconnect both busses
      DATA_in  <= (others=>'Z');
      tb_data  <= (others=>'Z');
    end if;
  end process IO_DATA;

process

  begin

-- Insert TEST BENCH Code Here

    RST <= '0';
    Rx_DATA_STB <= '0';
    SDI0 <= '0';
    SDI1 <= '0';
    Tx_DATA_STB <= '0';
    
    -- init the memory contents from file
    tb_mem_init        <= TRUE;
    tb_init_filename   <= "test_io/mem_init_00.txt";
    wait for Period * 4;
    tb_mem_init        <= FALSE;
    
    RST <= '1';
    
    wait;
    
    -- TODO : DUMP SOME SRAM
    
  end process;
end TEST;